﻿namespace mVids
{
    using MediaPortal.Configuration;
    using MediaPortal.Dialogs;
    using MediaPortal.GUI.Library;
    using MediaPortal.Profile;
    //using MediaPortal.ServiceImplementations;
    using System;
    using System.Collections.Generic;
    using System.Net;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Xml;

    public class lastFM
    {
        public bool addMatch = false;
        private char badChar = '"';
        private string bioLanguage;
        private string customStr;
        private List<mVids.artistInfo> foundArtists = new List<mVids.artistInfo>();
        private mVids.artistInfo resultChosen;

        public lastFM()
        {
            Settings settings = new Settings(Config.GetFolder(Config.Dir.Config) + "/MediaPortal.xml", false);
            string str = settings.GetValue("mvid", "bioLanguage");
            if (str != "")
            {
                this.bioLanguage = str;
            }
            else
            {
                this.bioLanguage = "en";
            }
            settings.Dispose();
        }

        private returntype chooseResultMPOpen(List<mVids.artistInfo> choices, string rawArtist, List<string> dbArtists)
        {
          GUIDialogMenu window = (GUIDialogMenu)GUIWindowManager.GetWindow(0x7dc);
            window.Reset();
            window.SetHeading("Choose match for: " + rawArtist);
            window.Add("[Skip This Time]");
            foreach (mVids.artistInfo info in choices)
            {
                if (dbArtists.Contains(info.name))
                {
                    window.Add(info.name + " (Exists in local DB)");
                }
                else
                {
                    window.Add(info.name);
                }
            }
            window.DoModal(GUIWindowManager.ActiveWindow);
            if ((window.SelectedId > 1) && (window.SelectedId > 1))
            {
                this.resultChosen = choices[window.SelectedId - 2];
                return returntype.confirmed;
            }
            return returntype.skip;
        }

        private string DecodeUtf8String(string aUtf8String)
        {
            try
            {
                byte[] bytes = Encoding.UTF8.GetBytes(aUtf8String);
                Encoding encoding = Encoding.Default;
                return Encoding.ASCII.GetString(bytes);
            }
            catch (Exception exception)
            {
                Log.Warn("AudioscrobblerUtils: Could not convert to system encoding - {0}, {1}", new object[] { aUtf8String, exception.Message });
                return aUtf8String;
            }
        }

        public mVids.artistInfo findArtist(string rawArtist, List<string> dbArtists)
        {
            XmlDocument document = new XmlDocument();
            WebClient client = new WebClient {
                Encoding = Encoding.UTF8
            };
            try
            {
                Log.Info("Music Video DB - Connecting to last.fm at URL http://ws.audioscrobbler.com/2.0/?method=artist.search&artist=" + rawArtist.Trim() + "&api_key=REMOVED", new object[0]);
                document.LoadXml(client.DownloadString("http://ws.audioscrobbler.com/2.0/?method=artist.search&artist=" + rawArtist.Trim() + "&api_key=fc769902e5def9584606dfb695b5fc92"));
            }
            catch (WebException exception)
            {
                Log.Error("Music Video DB - An error ocurred when connecting to last.fm findArtist URL, error: {0}", new object[] { exception.ToString() });
            }
            catch (Exception exception2)
            {
                Log.Error("Music Video DB - A generic error ocurred when connecting to last.fm findArtist URL, error: {0}", new object[] { exception2.ToString() });
            }
            XmlNodeList list = document.SelectNodes("/lfm/results/artistmatches/artist");
            List<mVids.artistInfo> choices = new List<mVids.artistInfo>();
            foreach (XmlNode node in list)
            {
                mVids.artistInfo info;
                info = new mVids.artistInfo {
                    name = node.SelectSingleNode("name").InnerText,
                    lfmName = this.DecodeUtf8String(node.SelectSingleNode("url").InnerText)
                };
                info.lfmName = info.lfmName.Remove(0, info.lfmName.LastIndexOf("/") + 1);
                choices.Add(info);
            }
            if (choices.Count != 0)
            {
                if (choices[0].name.ToLower().Trim() == rawArtist.ToLower().Trim())
                {
                    this.resultChosen = choices[0];
                    Log.Info("Music Video DB - Auto Matched {0} to {1} at {2}", new object[] { rawArtist.ToLower().Trim(), this.resultChosen.name, this.resultChosen.lfmName });
                    return this.resultChosen;
                }
                if (GUIWindowManager.Initalized)
                {
                    switch (this.chooseResultMPOpen(choices, rawArtist, dbArtists))
                    {
                        case returntype.confirmed:
                            this.customStr = "";
                            this.resultChosen.addMatch = true;
                            return this.resultChosen;

                        case returntype.skip:
                            this.customStr = "";
                            this.addMatch = false;
                            return null;

                        case returntype.custom:
                            this.addMatch = true;
                            this.resultChosen = this.findArtist(this.customStr, dbArtists);
                            return this.resultChosen;
                    }
                    return this.resultChosen;
                }
                this.foundArtists = choices;
            }
            return null;
        }

        public mVids.artistInfo getArtistInfo(mVids.artistInfo aI)
        {
            Exception exception2;
            XmlDocument document = new XmlDocument();
            WebClient client = new WebClient {
                Encoding = Encoding.UTF8
            };
            try
            {
                document.LoadXml(client.DownloadString("http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist=" + aI.lfmName + "&lang=" + this.bioLanguage + "&api_key=fc769902e5def9584606dfb695b5fc92"));
            }
            catch (WebException exception)
            {
                Log.Error("Music Video DB - Web error ocurred when connecting to last.fm URL {1} {0}", new object[] { Environment.NewLine + "Music Video DB - " + exception.Message, "http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist=" + aI.lfmName + "&lang=" + this.bioLanguage + "&api_key=..." });
                aI.notFound = true;
                Log.Debug("Music Video DB - last.fm artist {0} not found", new object[] { aI.lfmName });
                return aI;
            }
            catch (Exception exception3)
            {
                exception2 = exception3;
                Log.Error("Music Video DB - A generic error ocurred when connecting to last.fm getArtistInfo URL, error: {0}", new object[] { exception2.ToString() });
            }
            XmlNodeList list = document.SelectNodes("/lfm/artist/similar/artist");
            if (list.Count > 0)
            {
                try
                {
                    foreach (XmlNode node in list)
                    {
                        string innerText = node.SelectSingleNode("url").InnerText;
                        aI.similar = aI.similar + "|" + innerText.Remove(0, innerText.LastIndexOf("/") + 1);
                        Log.Debug("Music Video DB - Added similar artist {0} for {1}", new object[] { innerText.Remove(0, innerText.LastIndexOf("/") + 1), aI.name });
                    }
                    object[] objArray = new object[] { aI.similar.Split("|".ToCharArray()).Length.ToString(), aI.name };
                    Log.Info("Music Video DB - Found {0} similar artists for {1}", objArray);
                }
                catch (Exception exception4)
                {
                    exception2 = exception4;
                    Log.Error("Music Video DB - Error getting similar artists for {0}, error was: {1}", new object[] { aI.name, exception2.ToString() });
                }
            }
            try
            {
                if ((document.SelectSingleNode("/lfm/artist/bio/summary") != null) && (document.SelectSingleNode("/lfm/artist/bio/summary").InnerText != ""))
                {
                    aI.bioSummary = document.SelectSingleNode("/lfm/artist/bio/summary").InnerText.Replace(this.badChar.ToString(), "'");
                    aI.bioSummary = aI.bioSummary.Replace("&quot;", "'");
                    aI.bioSummary = aI.bioSummary.Replace("&amp;", "&");
                    aI.bioSummary = Regex.Replace(aI.bioSummary, "<.*?>", "");
                    Log.Info("Music Video DB - Grabbed Biographical Summary for {0}", new object[] { aI.name });
                    Log.Debug("Music Video DB - Summary is {0}", new object[] { aI.bioSummary });
                }
                else
                {
                    Log.Info("Music Video DB - No Biographical Summary found for {0}", new object[] { aI.name });
                }
            }
            catch (Exception exception5)
            {
                exception2 = exception5;
                Log.Error("Music Video DB - Error getting biographical summary for {0}, error was: {1}", new object[] { aI.name, exception2.ToString() });
            }
            try
            {
                if ((document.SelectSingleNode("/lfm/artist/bio/content") != null) && (document.SelectSingleNode("/lfm/artist/bio/content").InnerText != ""))
                {
                    aI.bioContent = document.SelectSingleNode("/lfm/artist/bio/content").InnerText.Replace(this.badChar.ToString(), "'");
                    aI.bioContent = aI.bioContent.Replace("&quot;", "'");
                    aI.bioContent = Regex.Replace(aI.bioContent, "<.*?>", string.Empty);
                    Log.Info("Music Video DB - Grabbed Biographical Content for {0}", new object[] { aI.name });
                    Log.Debug("Music Video DB - Content is {0}", new object[] { aI.bioContent });
                }
                else
                {
                    Log.Info("Music Video DB - No Biographical Content found for {0}", new object[] { aI.name });
                }
            }
            catch (Exception exception6)
            {
                exception2 = exception6;
                Log.Error("Music Video DB - Error getting biographical content for {0}, error was: {1}", new object[] { aI.name, exception2.ToString() });
            }
            try
            {
                XmlNodeList list2 = document.SelectNodes("/lfm/artist/image");
                foreach (XmlNode node in list2)
                {
                    if (node.Attributes.Item(0).Value == "large")
                    {
                        aI.imageURL = node.InnerText;
                    }
                }
                if (aI.imageURL == null)
                {
                    Log.Info("Music Video DB - No image URL found for {0}", new object[] { aI.name });
                }
                else
                {
                    Log.Info("Music Video DB - Found image for {0} at {1}", new object[] { aI.name, aI.imageURL });
                }
            }
            catch (Exception exception7)
            {
                exception2 = exception7;
                Log.Error("Music Video DB - Error getting image URL for {0}, error was: {1}", new object[] { aI.name, exception2.ToString() });
            }
            if (aI.tags == "")
            {
                aI = this.getTopTags(aI);
            }
            return aI;
        }

        public List<mVids.artistInfo> getLastfmMatches()
        {
            if (this.foundArtists.Count == 0)
            {
                return null;
            }
            return this.foundArtists;
        }

        public mVids.artistInfo getTopTags(mVids.artistInfo aI)
        {
            try
            {
                XmlDocument document = new XmlDocument();
                WebClient client = new WebClient();
                document.LoadXml(client.DownloadString("http://ws.audioscrobbler.com/2.0/?method=artist.gettoptags&artist=" + aI.lfmName + "&api_key=fc769902e5def9584606dfb695b5fc92"));
                Settings settings = new Settings(Config.GetFolder(Config.Dir.Plugins) + "/Windows/mVids.xml", true);
                int count = settings.GetValueAsInt("mvid", "maxtagstograb", 5);
                if (settings.GetValueAsBool("mvid", "graballtags", false))
                {
                    count = 0x3e8;
                }
                settings.Dispose();
                XmlNodeList list = document.SelectNodes("/lfm/toptags/tag");
                if (list.Count > 0)
                {
                    if (list.Count < count)
                    {
                        count = list.Count;
                    }
                    for (int i = 0; i < count; i++)
                    {
                        if (i == 0)
                        {
                            aI.tags = list[i].SelectSingleNode("name").InnerText;
                        }
                        else
                        {
                            aI.tags = aI.tags + "|" + list[i].SelectSingleNode("name").InnerText;
                        }
                    }
                }
                if (aI.tags != null)
                {
                    Log.Info("Music Video DB - Grabbed tags for {0}", new object[] { aI.name });
                    foreach (string str in aI.tags.Split("|".ToCharArray()))
                    {
                        Log.Debug("Music Video DB - Tag {0}", new object[] { str });
                    }
                }
                else
                {
                    Log.Info("Music Video DB - No tags found for {0}", new object[] { aI.name });
                }
                return aI;
            }
            catch (Exception exception)
            {
                Log.Error("Music Video DB - Error getting tags for {0}, error: {1}", new object[] { aI.name, exception.ToString() });
                return aI;
            }
        }

        private enum returntype
        {
            skip,
            confirmed,
            custom,
            choose
        }
    }
}

